﻿<?xml version="1.0" encoding="utf-8"?><!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"><html>
<!-- saved from url=(0033)http://research.microsoft.com/pex -->
<head><link rel="StyleSheet" href="er.common.css" type="text/css" /><script src="er.common.js" type="text/javascript"> </script><link rel="SHORTCUT ICON" href="favicon.ico" /><link rel="icon" href="favicon.ico" type="image/x-icon" /><title>C:\Users\AO\Documents\Visual Studio 2010\AutomaTones3\automatones\AutomaTones\AutomaTones\Controller\MainController.cs</title></head><body><div class="banner"></div><h2 id="top">C:\Users\AO\Documents\Visual Studio 2010\AutomaTones3\automatones\AutomaTones\AutomaTones\Controller\MainController.cs</h2><div class="toggle"><p class="copyright"><a class="usercodeundertestcovered">user code under test</a>, 
  <span class="usercodeundertestnotcovered">user code under test (not covered)</span>, 
  <a class="userortestcodecovered">user code or test</a>, 
  <span class="userortestcodenotcovered">user code or test (not covered)</span>,
  <span class="tagged">tagged</span></p><table><tr><th>Methods</th></tr><tr><th /></tr></table><div class="toggle"><a class="button" href="#ID0EL">first</a><pre class="coverage">/**
 * The Maincontroller knows all controllers in the system. Thus master volume, pause, 
 * play etc. can easily be controlled from here. Views can register themselves to the maincontroller
 * on when apropiate. The main controller choses what IController sub-type that will control a 
 * registring view.
 * Author: Anders Høst | ahkj@itu.dk
 * Date: 05 Dec 2010
 */

using System;
using System.Collections.Generic;
using System.Diagnostics.Contracts;
using System.Linq;
using System.Threading;
using AutomaTones.HW_Sense_Compute;
using AutomaTones.Model.MIDI;
using AutomaTones.Model.MIDI.Mappers;
using AutomaTones.View;
using AutomaTones.View.Launchpad_View;
using AutomaTones.View.Midi_Out_View;
using Microsoft.Pex.Framework;
using Midi;

namespace AutomaTones.Controller {
    [PexClass]
    public partial class MainController {
        <span id="ID0EL"><a class="button" href="#top">top</a>|<a class="button" href="#ID0ECD">next</a></span><a class="userortestcodecovered">private List&lt;IController&lt;IView&gt;&gt; _CAcontrollers = new List&lt;IController&lt;IView&gt;&gt;();</a>
        private IController&lt;IMasterView&gt; _masterViewController;
        <a class="userortestcodecovered">private List&lt;Channel&gt; _midiChannels = new List&lt;Channel&gt;();</a>
        private IHardwareView _hardWareView;
        private ComputeLaunchpad _computeLaunchpad;
        public static bool LaunchpadConnected;
        public static Tempo Tempo;

        [PexMethod]
        public void Init() <a class="button" href="#ID0EL">prev</a>|<span id="ID0ECD"><a class="button" href="#top">top</a>|<a class="button" href="#ID0EWCAC">next</a></span><a class="userortestcodecovered">{</a>
            // Global tempo used
            <a class="userortestcodecovered">Tempo = new Tempo(110);</a>
            <a class="userortestcodecovered">AddChannels();</a>
            
            // Try to make the connection to the Launchpad. Handles the exception if it's not present.
            try <a class="userortestcodecovered">{</a>
                <a class="userortestcodecovered">SetupLaunchpad();</a>
                <a class="userortestcodecovered">LaunchpadConnected = true;</a>
            <a class="userortestcodecovered">}</a>
            <span class="userortestcodenotcovered">catch (Exception ex)</span> <span class="userortestcodenotcovered">{</span>
                <span class="userortestcodenotcovered">Console.WriteLine(ex.Message);</span>
                <span class="userortestcodenotcovered">LaunchpadConnected = false;</span>
            <span class="userortestcodenotcovered">}</span>
            <a class="userortestcodecovered">ThreadPool.QueueUserWorkItem(delegate { Run(); });</a>
        <a class="userortestcodecovered">}</a>

        /// &lt;summary&gt;
        /// Add a view that implements the IVEW interface.
        /// &lt;/summary&gt;
        /// &lt;param name="view"&gt;&lt;/param&gt;
        [PexMethod]
        public void AddIView(IView view) {
            Contract.Requires(view != null);
            Contract.Ensures(Contract.OldValue(_CAcontrollers.Count) &lt; _CAcontrollers.Count);
            IController&lt;IView&gt; con = new CAViewController();

            con.Channels = MidiChannels;
            con.AddView(view);
            if(_hardWareView!=null)
              ((CAViewController)con).AddHwView(_hardWareView);

            con.SetUp();
            lock (_CAcontrollers)
            {
                ((List&lt;IController&lt;IView&gt;&gt;) _CAcontrollers).Add(con);
            }
            ConnectLaunchpadToControllers();
        }

        /// &lt;summary&gt;
        /// The heart beat of the system. Pulsates a base beat to all VaViewControllers.
        /// &lt;/summary&gt;
        [PexMethod]
        private void Run() {
            while (true) {
                lock (_CAcontrollers) {
                    foreach (CAViewController c in _CAcontrollers) {
                        if (c.IsPLaying) {
                            c.Evolve();
                        }
                    }
                    foreach (CAViewController c in _CAcontrollers) {
                        if (c.IsPLaying) {
                            c.Play();
                        }
                    }
                }
                Thread.Sleep(Tempo.SixteenthNote());
            }
        }

        /// &lt;summary&gt;
        /// Adding a masterview to a maincontroller will replace the existing masterview.
        /// &lt;/summary&gt;
        /// &lt;param name="?"&gt;&lt;/param&gt;
       [PexMethod]
        public void AddMasterView(IMasterView imv) <a class="button" href="#ID0EL">prev</a>|<span id="ID0EWCAC"><a class="button" href="#top">top</a>|<a class="button" href="#ID0EEHAC">next</a></span><a class="userortestcodecovered">{</a>
            <a class="userortestcodecovered">this._masterViewController = (IController&lt;IMasterView&gt;)new MasterViewController(this);</a>
            <a class="userortestcodecovered">((IController&lt;IMasterView&gt;)_masterViewController).AddView(imv);</a>
            <a class="userortestcodecovered">this._masterViewController.SetUp();</a>
        <a class="userortestcodecovered">}</a>

        /// &lt;summary&gt;
        /// Property for Midichannels. The channels propogates from here to the rest of the controllers.
        /// &lt;/summary&gt;
        public List&lt;Channel&gt; MidiChannels {
            get { return _midiChannels; }
            set { _midiChannels = value; }
        }

        [PexMethod]
        private void SetupLaunchpad() <a class="button" href="#ID0EL">prev</a>|<span id="ID0EEHAC"><a class="button" href="#top">top</a>|<a class="button" href="#ID0EKOAC">next</a></span><a class="userortestcodecovered">{</a>              
            <a class="userortestcodecovered">ConnectLaunchpad clp = new ConnectLaunchpad();</a>
            <a class="userortestcodecovered">SenseLaunchpad slp = new SenseLaunchpad();</a>
            <a class="userortestcodecovered">_computeLaunchpad = slp.ComputeLaunchpad;</a>
            <a class="userortestcodecovered">_hardWareView = new LaunchPad();</a>
            <a class="userortestcodecovered">ConnectLaunchpadToControllers();</a>
            <a class="userortestcodecovered">((LaunchPad)_hardWareView).ClearGrid();</a>
            <a class="userortestcodecovered">slp.StartSensing();</a>
            
        <a class="userortestcodecovered">}</a>

        private void ConnectLaunchpadToControllers() <a class="button" href="#ID0EL">prev</a>|<span id="ID0EKOAC"><a class="button" href="#top">top</a>|<a class="button" href="#ID0EAHAE">next</a></span><a class="userortestcodecovered">{</a>
            <a class="userortestcodecovered">foreach</a> (<span class="userortestcodenotcovered">CAViewController controller</span> <a class="userortestcodecovered">in</a> <a class="userortestcodecovered">_CAcontrollers</a>)
            <span class="userortestcodenotcovered">{</span>
                <span class="userortestcodenotcovered">if (LaunchpadConnected)</span> <span class="userortestcodenotcovered">{</span>
                    <span class="userortestcodenotcovered">_computeLaunchpad.LaunchpadEvent += controller.LaunchpadClicked;</span>
                    <span class="userortestcodenotcovered">_computeLaunchpad.StateButtonEvent += controller.StateButtonDown;</span>
                    <span class="userortestcodenotcovered">_computeLaunchpad.StateChangeEvent += controller.State;</span>
                    <span class="userortestcodenotcovered">_computeLaunchpad.OkButtonEvent += controller.Ok;</span>
                    <span class="userortestcodenotcovered">_computeLaunchpad.ClearButtonEvent += controller.ResetGrid;</span>
                <span class="userortestcodenotcovered">}</span>
            <span class="userortestcodenotcovered">}</span>
        <a class="userortestcodecovered">}</a>

        /// &lt;summary&gt;
        /// Add channels to the system. Calling this method will make the 
        /// Maincontroller detect all available channels.
        /// &lt;/summary&gt;
        private void AddChannels() <a class="button" href="#ID0EL">prev</a>|<span id="ID0EAHAE"><a class="button" href="#top">top</a>|<a class="button" href="#ID0ERKAE">next</a></span><a class="userortestcodecovered">{</a>
            <a class="userortestcodecovered">List&lt;Channel&gt; avalChannels = Enum.GetValues(typeof (Channel)).Cast&lt;Channel&gt;().ToList();</a>
            <a class="userortestcodecovered">_midiChannels = avalChannels;</a>
        <a class="userortestcodecovered">}</a>

        /********************************************************************************
         * MasterViewController as an inner class so it can access the CaViewControllers
         ********************************************************************************/

       class MasterViewController : IController&lt;IMasterView&gt; {
           private IMasterView _view;
           <a class="button" href="#ID0EL">prev</a>|<span id="ID0ERKAE"><a class="button" href="#top">top</a>|<a class="button" href="#ID0EJQAE">next</a></span><a class="userortestcodecovered">private int _masterChannel = 16;</a>
           private ConnectVirtualMidi _vm;
           private MidiOut _mo;
   
           <a class="userortestcodecovered">public MasterViewController(MainController m)</a> <a class="userortestcodecovered">{</a>
               <a class="userortestcodecovered">this.MainController = m;</a>
               <a class="userortestcodecovered">_vm = new ConnectVirtualMidi();</a>
               <a class="userortestcodecovered">_mo = _mo = new MidiOut(Channel.Channel16, new BechTranslator());</a>
           <a class="userortestcodecovered">}</a>
   
           /// &lt;summary&gt;
           /// Add the IMasterView to this controller.
           /// &lt;/summary&gt;
           /// &lt;param name="v"&gt;&lt;/param&gt;
           public void AddView(IMasterView v) <a class="button" href="#ID0EL">prev</a>|<span id="ID0EJQAE"><a class="button" href="#top">top</a>|<a class="button" href="#ID0ENSAE">next</a></span><a class="userortestcodecovered">{</a>
               Contract.Requires(v != null);
               Contract.Requires(this.MainController != null);
               Contract.Ensures(this._view == v);
               <a class="userortestcodecovered">_view = v;</a>
           <a class="userortestcodecovered">}</a>
           [PexMethod]
           public void SetUp() <a class="button" href="#ID0EL">prev</a>|<span id="ID0ENSAE"><a class="button" href="#top">top</a></span><a class="userortestcodecovered">{</a>
               <a class="userortestcodecovered">_view.OnForwardButtonClickEvent += Forward;</a>
               <a class="userortestcodecovered">_view.OnPauseButtonClickEvent += Pause;</a>
               <a class="userortestcodecovered">_view.OnPlayButtonClickEvent += Play;</a>
               <a class="userortestcodecovered">_view.OnRewindButtonClickEvent += Rewind;</a>
               <a class="userortestcodecovered">_view.OnVolumeChangeEvent += VolumeChanged;</a>
           <a class="userortestcodecovered">}</a>

           /// &lt;summary&gt;
           /// Send a Forward message to all CA
           /// &lt;/summary&gt;
           [PexMethod]
           public void Forward() {
               lock (MainController._CAcontrollers){
                   foreach (CAViewController cac in MainController._CAcontrollers){
                       cac.Forward();
                   }
               }
           }
   
           /// &lt;summary&gt;
           /// Send pause message to all CA
           /// &lt;/summary&gt;
           [PexMethod]
           public void Pause(){
               lock (MainController._CAcontrollers) {
                   foreach (CAViewController cac in MainController._CAcontrollers) {
                       cac.Pause();
                   }
               }
           }
   
           /// &lt;summary&gt;
           /// Send Play to all CA
           /// &lt;/summary&gt;
           [PexMethod]       
           public void Play() {
               lock (MainController._CAcontrollers) {
                   foreach (CAViewController cac in MainController._CAcontrollers) {
                       cac.PlaySentFromUser();
                   }
               }
           }
   
           /// &lt;summary&gt;
           /// Send Rewind to all CA
           /// &lt;/summary&gt;
           [PexMethod]
           public void Rewind() {
               lock (MainController._CAcontrollers) {
                   foreach (CAViewController cac in MainController._CAcontrollers) {
                       cac.Rewind();
                   }
               }
           }
   
           /// &lt;summary&gt;
           /// Turn down the volume. It directs the call directly to the midi out, thus not affecting the CA.
           /// &lt;/summary&gt;
           /// &lt;param name="volume"&gt;&lt;/param&gt;
           [PexMethod]      
           public void VolumeChanged(int volume) {
                _mo.SetVolume(volume);
           }

           /// &lt;summary&gt;
           /// As is, evolve is omitted for this implementation, this might be useful for an some extende use of CA
           /// &lt;/summary&gt;
           public void Evolve(){}

           private MainController MainController { get; set; }
   
           public bool IsPLaying { get; set; }
   
           public int Volume { get; set; }

           public List&lt;Channel&gt; Channels { get; set; }
           [ContractInvariantMethod]
           private void Invariant() {
               Contract.Invariant(0 &lt;= Volume &amp;&amp; Volume &lt;= 100);
           }
       }
   }
}
</pre></div></div><hr /><table width="100%"><tr><td valign="top"><span class="copyright">Copyright (c) Microsoft Corporation. All rights reserved.</span><br /><span class="button" onclick="copySourceToClipboard()">Copy full source to clipboard</span></td></tr></table><div id="debugdiv"> </div></body></html>